package com.weituotian.moudle.member.service.impl;

import com.weituotian.core.exception.ServiceException;
import com.weituotian.core.jpa.domain.JPQLParamsSetter;
import com.weituotian.core.jpa.domain.SimpleSpecification;
import com.weituotian.core.jpa.domain.Specification;
import com.weituotian.core.utils.DtoUtils;
import com.weituotian.core.utils.PageInfo;
import com.weituotian.core.utils.ShiroUtil;
import com.weituotian.moudle.member.dao.IAttachmentDao;
import com.weituotian.moudle.member.dao.IMemberDao;
import com.weituotian.moudle.member.dao.IPartitionDao;
import com.weituotian.moudle.member.dao.IVideoDao;
import com.weituotian.moudle.member.entity.*;
import com.weituotian.moudle.member.entity.enums.VideoState;
import com.weituotian.moudle.member.entity.vo.VideoListVo;
import com.weituotian.moudle.member.entity.vo.VideoVo;
import com.weituotian.moudle.member.service.IVideoService;
import com.weituotian.system.dao.IBaseDao;
import com.weituotian.system.entity.User;
import com.weituotian.system.entity.enums.OpenState;
import com.weituotian.system.service.impl.AdminBaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 会员视频服务
 * Created by ange on 2017/2/22.
 */
@Service("videoService")
@Transactional
public class VideoService extends AdminBaseService<Video, Integer> implements IVideoService {


    private final IVideoDao videoDao;

    private final IPartitionDao partitionDao;

    private final IAttachmentDao attachmentDao;

    private final IMemberDao memberDao;

    @Autowired
    public VideoService(IVideoDao videoDao, IAttachmentDao attachmentDao, IPartitionDao partitionDao, IMemberDao memberDao) {
        this.videoDao = videoDao;
        this.attachmentDao = attachmentDao;
        this.partitionDao = partitionDao;
        this.memberDao = memberDao;
    }

    @Override
    public IBaseDao<Video, Integer> getBaseDao() {
        return videoDao;
    }

    @Override
    public Specification<Video> pageSpecification(PageInfo<?> pageInfo) {
        return null;
    }

    @Override
    public void findPageMember(Integer userId, PageInfo<Video> pageInfo) {

        List<Video> content = getBaseDao().findPage(new SimpleSpecification<Video>() {

            @Override
            public void beforeSelectList(Root<Video> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //fetch资源,一次性加载出来
                root.fetch(Video_.attachment, JoinType.LEFT);
                root.fetch(Video_.partition, JoinType.LEFT);
                root.fetch(Video_.member, JoinType.LEFT);
            }

            @Override
            public Predicate toPredicate(Root<Video> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                List<Predicate> predicates = new ArrayList<Predicate>();

                //限定上传
                predicates.add(cb.equal(root.get(Video_.member).get(Member_.id), userId));
                //限定开启状态
                predicates.add(cb.equal(root.get(Video_.openState), OpenState.OPEN));

                for (Map.Entry<String, Object> entry : pageInfo.getCondition().entrySet()) {
                    String name = entry.getKey();
                    String value = (String) entry.getValue();
                    if (name.equals("name")) {
                        predicates.add(cb.like(root.get("name"), "%" + value + "%"));
                    } else if (name.equals("partition")) {
                        predicates.add(cb.equal(root.get(Video_.partition).get(Partition_.id), value));
                    } else {
                        predicates.add(cb.equal(root.get(name), value));
                    }
                }

                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        }, pageInfo);
        pageInfo.setList(content);
    }

    public void findPageMemberVo(Integer userId, PageInfo<VideoListVo> pageInfo) {

        String where = "1=1 ";
        String like = "";
        Integer partitionId = 0;
        if (pageInfo.getCondition()!=null) {

            for (Map.Entry<String, Object> entry : pageInfo.getCondition().entrySet()) {
                String name = entry.getKey();
                String value = (String) entry.getValue();
                if (name.equals("name")) {
                    like = "%" + value + "%";
                    where += "AND video.title like :like ";
                } else if (name.equals("partition") && !value.equals("")) {
                    partitionId = Integer.valueOf(value);
                    where += "AND partition.id = :partitionId ";
                }
            }

        }

        String finalLike = like;
        Integer finalPartitionId = partitionId;
        List<VideoListVo> vos = videoDao.findPageMember(userId, where, pageInfo, new JPQLParamsSetter() {
            @Override
            public void onSetParams(Query query) {
                if (!finalLike.equals("")) {
                    query.setParameter("like", finalLike);
                }
                if (!finalPartitionId.equals(0)) {
                    query.setParameter("partitionId", finalPartitionId);
                }
            }
        });
        pageInfo.setList(vos);

    }

    @Override
    public void addByDto(VideoVo videoVo) {
        User user = ShiroUtil.getCurrentUser();

        Attachment attachment = attachmentDao.findOne(videoVo.getAttachmentId());
        if (attachment.getUserId() != user.getId()) {
            throw new ServiceException("视频所有者出现了问题");
        }

        if (videoDao.findByAttachmentId(videoVo.getAttachmentId()).size() >= 1) {
            throw new ServiceException("不能重复上传视频");
        }

        if (videoDao.findByTitle(videoVo.getTitle()).size() >= 1) {
            throw new ServiceException("不能重复上传视频");
        }

        Partition partition = partitionDao.findOne(videoVo.getPartitionId());

        Member member = memberDao.findOne(user.getId());

        Video video = new Video();
        video.setPartition(partition);

        //附件
        attachment.setTemp(false);//从临时附件变为正式附件
        video.setAttachment(attachment);
        video.setMember(member);

        Date date = new Date();
        video.setCreateTime(date);
        video.setUpdateTime(date);
        video.setClick(0);
        video.setCollect(0);
        video.setPlay(0);

        //状态为审核中
        video.setVideoState(VideoState.Auditing);
        video.setOpenState(OpenState.OPEN);//开启状态,没有被用户删除

        //更新会员上传视频的数量
        Integer count = videoDao.getMemberVideosCount(user.getId());
        member.setVideos(count);


        DtoUtils.copyProperties(videoVo, video);

        videoDao.persist(video);
    }

    @Override
    public void updateByDto(VideoVo videoVo, Integer id) {
        Video video = videoDao.findOne(id);

        User user = ShiroUtil.getCurrentUser();

        Attachment attachment = attachmentDao.findOne(videoVo.getAttachmentId());
        if (attachment.getUserId() != user.getId()) {
            throw new ServiceException("视频所有者出现了问题");
        }

        Partition partition = partitionDao.findOne(videoVo.getPartitionId());

        video.setPartition(partition);
        video.setAttachment(attachment);
        video.setVideoState(VideoState.Auditing);//状态为审核中

        DtoUtils.copyProperties(videoVo, video);
    }

    @Override
    public void deleteByIds(Integer[] ids) {
        for (Integer id : ids) {
            Video video = videoDao.findOne(id);
            video.setOpenState(OpenState.CLOSE);
        }
    }

    public Video findOneFetch(Integer id){
        return videoDao.findOneFetch(id);
    }
}
